/*
 * sysmo 服务器监控项脚本对象
 * Copyright (C) 2009  YuLicheng
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.sysmo.server.node.item;

import org.sysmo.communication.CommunicationInterface;
import org.sysmo.communication.CommunicationProtocol;
import org.w3c.dom.NodeList;

/**
 *
 * 脚本对象可用于存储任何类型的文件。包括二进制程序或文本文件。此对象一经创建后
 * 就不可更改，若要更改应创建新的对象。另外此对象也负责向客户端发送脚本。
 * <br />
 *
 * 脚本将使用指定的命令行来执行。命令行中使用${file}代替最终的脚本文件名。
 *
 * @author YuLicheng
 */
public class ItemScript {
    
    private CommunicationInterface client;
    private String commandLine;
    private String postfix;
    private int itemID;
    private ItemEvent event;

    /**
     * 创建一个新的脚本对象。
     *
     * @param client 端通讯协议接口
     * @param itemID 监控项ID。
     * @param event 监控项事件处理对象。
     */
    protected ItemScript(CommunicationInterface client, int itemID, 
            ItemEvent event) {
        this.event = event;
        this.client = client;
        this.itemID = itemID;
        this.commandLine = "";
        this.postfix = "";
    }

    /**
     * 获得此脚本的文件内容。此方法会从客户端获取相应的脚本数据。
     *
     * @return 脚本文件内容。
     */
    public byte[] getScriptFromClient() {
        byte[] script = new byte[0];
        try {
            String message = CommunicationProtocol.encapsulateWithItemID(
                    9, itemID, "<withFile>1</withFile>");
            client.sendString(message);
            event.waitEvent(11);
            //忽略客户端送回的设置信息
            script = client.getByteArray();
            event.exitEvent();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return script;
    }

    /**
     * 设置脚本数据。此方法会立即将脚本数据发送到客户端。
     *
     * @param scriptData 脚本数据。
     */
    public void sendScriptToClient(byte[] scriptData) {
        try {
            String message = CommunicationProtocol.encapsulateWithItemID(
                    7, itemID, getSettingsString() + "<withFile>1</withFile>");
            client.sendString(message);
            client.sendByteArray(scriptData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获得此脚本的命令行。
     *
     * @return 命令行。
     */
    public String getCommandLine() {
        return commandLine;
    }
    
    /**
     * 设置执行脚本的命令行。
     *
     * @param commandLine 命令行。
     */
    public void setCommandLine(String commandLine) {
        this.commandLine = commandLine;
    }

    /**
     * 获取脚本文件的后缀名。
     *
     * @return 脚本文件后缀名。
     */
    public String getPostfix() {
        return postfix;
    }

    /**
     * 设置脚本文件后缀名。由于一些操作系统使用后缀名来决定文件是否能够执行，因此在将
     * 脚本文件传送到客户端时同时需要将其后缀名一并发送，以保证此文件能够按照设置的命
     * 令行执行。
     *
     * @param postfix
     */
    public void setPostfix(String postfix) {
        this.postfix = postfix;
    }

    /**
     * 从客户端获取指定监控项的脚本设置。此方法不会从客户端读取脚本数据。
     */
    public void getSettingsFromClient() {
        try {
            String message = CommunicationProtocol.encapsulateWithItemID(
                    9, itemID, "<withFile>0</withFile>");
            client.sendString(message);
            event.waitEvent(11);
            NodeList list =
                    event.messageDocument.getElementsByTagName("commandLine");
            if (list.getLength() > 0) {
                this.commandLine = list.item(0).getFirstChild().getNodeValue();
            }
            list = event.messageDocument.getElementsByTagName("postfix");
            if (list.getLength() > 0) {
                this.commandLine = list.item(0).getFirstChild().getNodeValue();
            }
            list = event.messageDocument.getElementsByTagName("withFile");
            if (list.getLength() > 0) {
                if (list.item(0).getFirstChild().getNodeValue().equals("1")) {
                    client.getByteArray(); //忽略客户端发送的脚本数据。
                }
            }
            event.exitEvent();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将设置发送给客户端。此方法只发送脚本设置不会发送脚本文件的内容。
     */
    public void sendSettingsToClient() {
        try {
            String message = CommunicationProtocol.encapsulateWithItemID(
                    7, itemID, getSettingsString() + "<withFile>0</withFile>");
            client.sendString(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成当前设置的XML信息内容。
     *
     * @return XML数据字符串。
     */
    private String getSettingsString() {
        return "<commandLine><![CDATA[" + commandLine + "]]></commandLine>"
                + "<postfix><![CDATA[" + postfix + "]]></postfix>";
    }
}
